﻿#include "tcp_client.h"
#include "tcp_meta.h"

#include <QMessageBox>
#include <QHostInfo>
#include <QByteArray>
#include <QFileDialog>
#include <QByteArray>
#include <QBuffer>
#include <QImageReader>
#include <QDesktopServices>
#include <QMimeDatabase>
#include <QTextEdit>
#include <QVideoWidget>
#include <QMediaPlayer>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    setWindowTitle("P2P Client");
    resize(1520,900);
    this->setStyleSheet("background-color: rgb(198,252,252)");

//    logLabel = new QLabel("操作日志");
//    ContentListWidget = new QListWidget;
//    ContentListWidget->setStyleSheet("background-color: rgb(235,255,255)");

    myWidget = new QWidget;
    UserNameLabel = new QLabel("用户名:");
    UserNameLineEdit = new QLineEdit;
    UserNameLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    UserPasswdLabel = new QLabel("密码:");
    UserPasswdLineEdit = new QLineEdit;
    UserPasswdLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    ServerIPLabel = new QLabel("服务器IP:");
    ServerIPLineEdit = new QLineEdit("100.64.173.40");
    ServerIPLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    PortLabel = new QLabel("端口:");
    PortLineEdit = new QLineEdit;
    PortLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    EnterBtn = new QPushButton("登陆");
    EnterBtn->setStyleSheet("background-color: rgb(135,243,246)");
    SignBtn = new QPushButton("注册");
    SignBtn->setStyleSheet("background-color: rgb(135,243,246)");
    quitBtn = new QPushButton("注销");
    quitBtn->setStyleSheet("background-color: rgb(135,243,246)");

    ShareTableWidget = new QTableWidget;
    ShareTableWidget->setColumnCount(6);
    QStringList tableHead;
    tableHead << "文件名" << "大小" << "文件路径" << "IP" << "端口" << "选择";
    ShareTableWidget->setHorizontalHeaderLabels(tableHead);
    ShareTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ShareTableWidget->setStyleSheet("background-color: rgb(235,255,255)");
    FlushBtn = new QPushButton("我的共享文件");
    FlushBtn->setStyleSheet("background-color: rgb(164,242,255)");
    DisableBtn = new QPushButton("取消选中项共享");
    DisableBtn->setStyleSheet("background-color: rgb(164,242,255)");
    BreakPointBtn = new QPushButton("异常中断的文件");
    BreakPointBtn->setStyleSheet("background-color: rgb(164,242,255)");
    ShareBtn = new QPushButton("上传我的文件");
    ShareBtn->setStyleSheet("background-color: rgb(164,242,255)");

    ResultTableWidget = new QTableWidget;
    ResultTableWidget->setColumnCount(8);
    tableHead.clear();
    tableHead << "文件名" << "大小" << "文件路径" << "拥有者" << "状态" << "IP"<< "断点位置" << "选择";
    ResultTableWidget->setHorizontalHeaderLabels(tableHead);
    ResultTableWidget->setHorizontalHeaderLabels(tableHead);
    ResultTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ResultTableWidget->setStyleSheet("background-color: rgb(235,255,255)");
    SearchBtn = new QPushButton("搜索");
    SearchBtn->setStyleSheet("background-color: rgb(164,242,255); font-weight: bold;");
    SearchLineEdit = new QLineEdit;
    SearchLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    StopBtn = new QPushButton("中断下载");
    StopBtn->setStyleSheet("background-color: rgb(255,110,110); font-weight: bold;");
    ProgressBar = new QProgressBar;
    ProgressBar->setRange(0,100);
    DownloadBtn = new QPushButton("下载选中项");
    DownloadBtn->setStyleSheet("background-color: rgb(164,242,255)");
    timer = new QTimer();

    DirLineEdit = new QLineEdit;
    DirLineEdit->setStyleSheet("background-color: rgb(250,250,250)");
    SelectDirBtn = new QPushButton("选择保存位置");
    SelectDirBtn->setStyleSheet("background-color: rgb(164,242,255)");

    layout1 = new QGridLayout();
    layout2 = new QGridLayout();
    layout3 = new QGridLayout();
    mainLayout = new QGridLayout();

//    layout1->addWidget(logLabel,0,0);
//    layout1->addWidget(ContentListWidget,1,0,1,2);
    layout1->addWidget(UserNameLabel,2,0);
    layout1->addWidget(UserNameLineEdit,2,1);
    layout1->addWidget(UserPasswdLabel,3,0);
    layout1->addWidget(UserPasswdLineEdit,3,1);
    layout1->addWidget(ServerIPLabel,4,0);
    layout1->addWidget(ServerIPLineEdit,4,1);
    layout1->addWidget(PortLabel,5,0);
    layout1->addWidget(PortLineEdit,5,1);
    layout1->addWidget(EnterBtn,6,0,1,2);
    layout1->addWidget(SignBtn,7,0,1,2);
    layout2->addWidget(ShareTableWidget,1,0,1,4);
    layout2->addWidget(FlushBtn,0,0);
    layout2->addWidget(DisableBtn,0,1);
    layout2->addWidget(BreakPointBtn,0,2);
    layout2->addWidget(ShareBtn,0,3);
    layout3->addWidget(ResultTableWidget,1,0,1,2);
    layout3->addWidget(SearchLineEdit,0,0);
    layout3->addWidget(SearchBtn,0,1);
    layout3->addWidget(ProgressBar,5,0,1,2);
    layout3->addWidget(StopBtn,5,1);
    layout3->addWidget(quitBtn, 6, 0);
    layout3->addWidget(DirLineEdit,4,0);
    layout3->addWidget(SelectDirBtn,4,1);
    layout3->addWidget(DownloadBtn,2,0,1,2);


//    mainLayout->addLayout(layout1,0,0,2,2);
    mainLayout->addLayout(layout2,0,2,1,1);
    mainLayout->addLayout(layout3,1,2,1,1);
    myWidget->setLayout(mainLayout);
    setCentralWidget(myWidget);

    status = false;
    port = 8010;
    PortLineEdit->setText(QString::number(port));

    ServerIP = new QHostAddress;

    connect(EnterBtn,SIGNAL(clicked()),this,SLOT(slotEnter()));//登录按钮与登录函数绑定
    connect(SignBtn,SIGNAL(clicked()),this,SLOT(slotSignUp()));//注册按钮与注册函数绑定
    connect(BreakPointBtn,SIGNAL(clicked()),this,SLOT(slotBreakPoint()));//断点文件按钮与断点函数绑定
    connect(ShareBtn,SIGNAL(clicked()),this,SLOT(slotSendMeta()));//分享文件按钮
    connect(FlushBtn,SIGNAL(clicked()),this,SLOT(slotFlushShare()));//获取我的共享
    connect(DisableBtn,SIGNAL(clicked()),this,SLOT(slotDeleteShare()));//删除我的共享
    connect(SearchBtn,SIGNAL(clicked()),this,SLOT(slotSearch()));//搜索文件按钮
    connect(SelectDirBtn,SIGNAL(clicked()),this,SLOT(slotSelectDir()));//选择下载地址
    connect(DownloadBtn,SIGNAL(clicked()),this,SLOT(slotDownload()));//下载选中项按钮
    connect(StopBtn,SIGNAL(clicked()),this,SLOT(slotStopDownload()));//中断下载项按钮
    connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
    connect(quitBtn, &QPushButton::clicked, this, [=](){
        int length = 0;
        QString msg = UserName + ": leave chat room";
        FormatMsg(msg, OTHERMSG);//向服务器发送用户退出的信息
        if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
            return;
        }
        tcpSocket->disconnectFromHost();
        status = false;
        delete p2pserver;//删除该用户的p2p服务
        qDebug()<<"msg:"<<msg;
        emit close();
    });

    ShareBtn->setEnabled(false);
    FlushBtn->setEnabled(false);
    DisableBtn->setEnabled(false);
    BreakPointBtn->setEnabled(false);
    SearchBtn->setEnabled(false);
    DownloadBtn->setEnabled(false);
    StopBtn->setEnabled(false);

    tcpSocket = nullptr;
    p2pserver = nullptr;


    PreviewBtn = new QPushButton("预览");
    connect(PreviewBtn,SIGNAL(clicked()),this,SLOT(previewAll()));
    layout3->addWidget(PreviewBtn,3,0,1,2);
}

void MainWindow::timeout(){//如果下载任务数为0，则停止定时器
    if(tasks.count() == 0){
        timer->stop();
        return;
    }
    qDebug() << "在线进度" << tasks.at(0)->progress;
    ProgressBar->setValue(tasks.at(0)->progress);
    if(tasks.at(0)->progress == 100 || tasks.at(0)->status == false){
        if(tasks.at(0)->status == false)
            ProgressBar->setValue(0);
        delete tasks.at(0);//完成任务后从任务队列中删除该任务
        tasks.removeAt(0);
    }
}

void MainWindow::slotEnter(QString serverIp, QString username, QString password){
    if(!status){//与注册基本相同
        ServerIPLineEdit->setText(serverIp);
        QString ip = ServerIPLineEdit->text();
        UserNameLineEdit->setText(username);
        UserPasswdLineEdit->setText(password);
        if(!ServerIP->setAddress(ip)){
            QMessageBox::information(this,"wrong","server ip error");
            return ;
        }
        if(UserNameLineEdit->text() == ""){
            QMessageBox::information(this,"wrong","user name error");
            return ;
        }
        UserName = UserNameLineEdit->text();
        qDebug()<<"slotEnter进来了！";

        tcpSocket = new QTcpSocket(this);
        connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected()));
        connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));
        connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(DataReceived()));

        tcpSocket->connectToHost(*ServerIP,port);
        status = true;
    }
    else{//如果tcp连接状态为true，即已登入，用户现在的操作是注销
        int length = 0;
        QString msg = username + ": leave chat room";
        FormatMsg(msg, OTHERMSG);//向服务器发送用户退出的信息
        if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
            return;
        }
        tcpSocket->disconnectFromHost();
        status = false;
        delete p2pserver;//删除该用户的p2p服务
    }
}

void MainWindow::GetFileLog(){
    //在C:/Qt/p2plog所在的日志文件查询异常下载的文件信息。
    QString Filename;
    int rows = ResultTableWidget->rowCount();
    for(int i = 0; i < rows; ++i){
        if(ResultTableWidget->item(i,7)->checkState() == Qt::Checked
                && ResultTableWidget->item(i,4)->text() == "在线"){//如果该文件是要下载的，而且分享者在线，就进行下载
            Filename = ResultTableWidget->item(0,0)->text();
        }
    }

    QFile dlog("C:/Qt/p2plog/"+Filename+"log");
    QString Lastline;
    QByteArray line;
    if (dlog.open(QIODevice::ReadOnly | QIODevice::Text))
    {
         while (!dlog.atEnd())
         {
            line = dlog.readLine();
            qDebug() << line;
         }
         Lastline = line;
           dlog.close();
    }
    qDebug() << Lastline;

    int i = 0;
    int k =0;
    while(Lastline.at(k++) != ':');
    while(Lastline.at(i++) != ';');
    QString progress = Lastline.mid(k, i -k- 1);
    while(Lastline.at(k++) != ':');
    while(Lastline.at(i++) != ';');
    QString breakpoint1 = Lastline.mid(k, i -k- 1);
    while(Lastline.at(k++) != ':');
    while(Lastline.at(i++) != ';');
    QString loader = Lastline.mid(k, i -k- 1);
    while(Lastline.at(k++) != ':');
    while(Lastline.at(i++) != ';');
    QString owner = Lastline.mid(k, i -k- 1);
    while(Lastline.at(k++) != ':');
    while(Lastline.at(i++) != ';');
    QString filename = Lastline.mid(k, i -k- 1);

    breakpoint=breakpoint1;//中断文件下载后获取断点值
    qDebug()<<"用户"+loader+"中断文件"+filename+"的断点位置:"+breakpoint<<endl;

    QString Loader=UserNameLineEdit->text();
    QString msg = Loader+";"+UserName + ";" + filename + ";"+breakpoint+ ";";
    int length;
    FormatMsg(msg, UPDATELOG);//封装了UL作为控制信息
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
      }
  }


void MainWindow::slotSignUp(){//用于注册的槽函数
    if(!status){//如果还未建立tcp连接，就进行下列操作
        QString ip = ServerIPLineEdit->text();//获取服务器主机的ip地址
        if(!ServerIP->setAddress(ip)){//校验IP地址格式是否正确
            QMessageBox::information(this,"wrong","server ip error");
            return ;
        }
        if(UserNameLineEdit->text() == ""){//校验姓名
            QMessageBox::information(this,"wrong","user name error");
            return ;
        }
        if(UserPasswdLineEdit->text() == ""){//校验密码是否为空
            QMessageBox::information(this,"wrong","pass word error");
            return ;
        }
        UserName = UserNameLineEdit->text();//获取姓名
        QString passwd = UserPasswdLineEdit->text();//获取密码

        tcpSocket = new QTcpSocket(this);//新建套接字实例
        connect(tcpSocket,SIGNAL(connected()),this,SLOT(SignConnected()));//连接上后，调用注册业务的函数
        connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(SignDisconnected()));//断开连接时，调用注册断开函数
        connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(SignDataReceived()));//该套接字收到信息后，调用注册信息接收函数

        tcpSocket->connectToHost(*ServerIP,port);//与服务器建立套接字连接
        status = true;//将tcp连接状态设置为已连接
    }
}

void MainWindow::slotBreakPoint(){//向服务器查询断点异常文件的请求槽函数
    QString msg = UserName;
    int length;
    FormatMsg(msg, BREAKPOINT);

    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}
void MainWindow::slotSelectDir(){//选中文件下载位置
    QString dirname = QFileDialog::getExistingDirectory(this,"选择文件保存位置","/");
    DirLineEdit->setText(dirname+"/");
}

void MainWindow::slotDownload(){//用户点击下载文件时，调用该函数

    QString dirname = DirLineEdit->text();//获取文件要存储的位置
    if(dirname == ""){
        return;
    }
    int rows = ResultTableWidget->rowCount();
    bool flag = false;//用于判断定时器打开没
    for(int i = 0; i < rows; ++i){
        if(ResultTableWidget->item(i,7)->checkState() == Qt::Checked
                && ResultTableWidget->item(i,4)->text() == "在线"){//如果该文件是要下载的，而且分享者在线，就进行下载
            tcp_meta tm;
            tm.filename = ResultTableWidget->item(i,0)->text();
            tm.size = ResultTableWidget->item(i,1)->text().toLong();
            tm.filepath = ResultTableWidget->item(i,2)->text();
            tm.owner = ResultTableWidget->item(i,3)->text();
            tm.ip = ResultTableWidget->item(i,5)->text();
            tm.port = port;
            tm.breakpoint=ResultTableWidget->item(i,6)->text();

            tasks.append(new P2P_Download(this, tm));//往p2p下载任务中加入新的下载
            tasks.last()->moveToThread(&thread);
//            connect(this, SIGNAL(startDownload(QString)), tasks.last(), SLOT(start_as_client(QString)));
            connect(this, &MainWindow::startDownload, tasks.last(), &P2P_Download::start_as_client);
            thread.start();
            emit startDownload(dirname);
//            tasks.last()->start_as_client(dirname);//开始进行p2p下载任务
            qDebug() << "待下载的任务数量" << tasks.length();

            if(flag == false){
                qDebug() << "进入计时器"<<"当前进度"<<tasks.last()->progress;
                timer->start(250);//每过1s启动计时器槽函数，更新界面进度条
            }
            flag = true;
        }
    }
}

void MainWindow::slotStopDownload(){
//    int rows = ResultTableWidget->rowCount();
//    tcp_meta tm;
//    for(int i = 0; i < rows; ++i){
//        if(ResultTableWidget->item(i,7)->checkState() == Qt::Checked
//                && ResultTableWidget->item(i,4)->text() == "在线"){//如果该文件是要下载的，而且分享者在线，就进行下载
//            tm.breakpoint=ResultTableWidget->item(i,6)->text();
//            tm.filename = ResultTableWidget->item(i,0)->text();
//            tm.owner = ResultTableWidget->item(i,3)->text();
//            tm.filepath = ResultTableWidget->item(i,2)->text();
//        }
//    }

//    //在filepath/log/filename+log所在的日志文件查询异常下载的文件信息。
//    QString logPath=tm.filepath;
//    QFile dlog("C:/Qt/p2plog/"+tm.filename+"log");
//    QString Lastline;
//    QByteArray line;
//    if (dlog.open(QIODevice::ReadOnly | QIODevice::Text))
//    {
//         while (!dlog.atEnd())
//         {
//            line = dlog.readLine();
//            qDebug() << line;
//         }
//         Lastline = line;
//           dlog.close();
//    }
//    qDebug() << Lastline;

//    int i = 0;
//    int k =0;
//    while(Lastline.at(k++) != ':');
//    while(Lastline.at(i++) != ';');
//    QString progress = Lastline.mid(k, i -k- 1);
//    while(Lastline.at(k++) != ':');
//    while(Lastline.at(i++) != ';');
//    QString breakpoint1 = Lastline.mid(k, i -k- 1);
//    while(Lastline.at(k++) != ':');
//    while(Lastline.at(i++) != ';');
//    QString loader = Lastline.mid(k, i -k- 1);
//    while(Lastline.at(k++) != ':');
//    while(Lastline.at(i++) != ';');
//    QString owner = Lastline.mid(k, i -k- 1);
//    while(Lastline.at(k++) != ':');
//    while(Lastline.at(i++) != ';');
//    QString filename = Lastline.mid(k, i -k- 1);

//    breakpoint=breakpoint1;//中断文件下载后获取断点值
//    UserName=tm.owner;//owner
//    qDebug()<<"用户"+UserName+"中断文件"+filename+"的断点位置:"+breakpoint<<endl;


//    QString Loader=UserNameLineEdit->text();
//    QString msg = Loader+";"+UserName + ";" + filename + ";"+breakpoint+ ";";
//    int length;
//    FormatMsg(msg, UPDATELOG);//封装了UL作为控制信息
//    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
//        return;
//      }

    /************************以下是在用户登陆后查询他以往的异常下载记录，插入到数据库***************************/
    GetFileLog();
}

void MainWindow::slotSendMeta(){//用户上传共享文件的请求
    QString filename = QFileDialog::getOpenFileName(this,"选择要共享的文件","/","files (*)");
    QFileInfo info(filename);
    tcp_meta mt;
    int length = 0;

    if(filename == ""){
        return;
    }

    mt.filename = info.fileName();//上传文件的名称
    mt.size = info.size();//要上传文件的大小
    mt.ip = tcpSocket->localAddress().toString();//获取本机的ip地址
    mt.owner = UserName;
    mt.port = port;
    mt.filepath = info.filePath();
    QString msg = mt.toString();//将元数据转变为String格式，以#S#开头
    FormatMsg(msg, METAMSG);//将上传文件的消息格式化
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}

void MainWindow::slotFlushShare(){//向服务器发送获取我分享的文件的请求
    QString msg = UserName;
    int length;
    FormatMsg(msg, SHAREMSG);

    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}

void MainWindow::slotDeleteShare(){//向服务器发送删除文件的请求
    QString msg = UserName + ";";
    int rows = ShareTableWidget->rowCount();
    int length = 0;

    for(int i = 0; i < rows; ++i){
        if(ShareTableWidget->item(i,5)->checkState() == Qt::Checked){
            msg = msg + ShareTableWidget->item(i,0)->text() + ";";
        }
    }
    FormatMsg(msg, DELETEMSG);//将要删除的文件名传给服务器，让服务器删除文件
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}

void MainWindow::slotSearch(){//向服务器发送搜索文件的请求
    QString filename = SearchLineEdit->text();
    if(filename == ""){
        return ;
    }

    QString msg = UserName + ";" + filename + ";";
    int length;
    FormatMsg(msg, SEARCHMSG);
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}

void MainWindow::slotConnected(){
    qDebug()<<"tcp成功连接！";
    EnterBtn->setText("注销");
    ShareBtn->setEnabled(true);
    FlushBtn->setEnabled(true);
    DisableBtn->setEnabled(true);
    BreakPointBtn->setEnabled(true);
    SearchBtn->setEnabled(true);
    DownloadBtn->setEnabled(true);
    SignBtn->setEnabled(false);
    StopBtn->setEnabled(true);


    p2pserver = new P2P_Server(this, port + 1);//用户登录时建立一个p2p服务，也就是说这是用户就是一个提供p2p文件传输服务的服务器了

    int length = 0;
    QString passwd = UserPasswdLineEdit->text();
    QString msg = UserName + ";" + passwd + ";";
//    qDebug()<<"msg:"<<msg;
    FormatMsg(msg, NAMEMSG);//发送用户进行登录的消息
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){
        return;
    }
}

void MainWindow::SignConnected(){
    SignBtn->setEnabled(false);//成功tcp成功连接，则将注册按钮禁用

    int length = 0;
    QString passwd = UserPasswdLineEdit->text();//获取用户填写的密码
    QString msg = UserName + ";" + passwd + ";";//将用户名和密码分隔开
    FormatMsg(msg, SIGNMSG);//格式化要发送的数据
    if((length = tcpSocket->write(msg.toLatin1(),msg.length())) != msg.length()){//将写入的字节数与本来的字节数进行比较，如果不相等说明传输出错
        return;
    }
}

void MainWindow::DataReceived(){
    int flag = 0;//用于记录第一次进入该函数，也就是服务器第一次给出文件的消息
    while (tcpSocket->bytesAvailable() > 8) {
        char buf[1024];
        tcpSocket->read(buf,8);

        //解析头部信息
        QString head = buf;
        long msglen = 0;
        QString kind;
        if(head == "error|||"){
            return;
        }
        else{
            msglen = head.mid(2,6).toLong();
            kind = head.mid(0,2);
            tcpSocket->read(buf,msglen);
            buf[msglen] = 0;
        }

        QString msg = buf;//获取的消息
        if(kind == "RK"){ //resource messsage，用户获取自己分享过的文件的响应消息
            if(flag == 0){
                ShareTableWidget->clear();
                ShareTableWidget->setRowCount(0);
                QStringList tableHead;
                tableHead << "文件名" << "大小" << "文件路径" << "IP" << "端口" << "选择";
                ShareTableWidget->setHorizontalHeaderLabels(tableHead);
            }
            flag = 1;
            //更新我的共享文件的信息
            UpdateShareTableWidget(msg);
        }
        else if(kind == "SR"){ //search messsage，搜索想下载的文件的响应
            if(flag == 0){
                ResultTableWidget->clear();
                ResultTableWidget->setRowCount(0);
                QStringList tableHead;
                tableHead.clear();
                tableHead << "文件名" << "大小" << "文件路径" << "拥有者" << "状态" << "IP"<< "断点位置" << "选择";
                ResultTableWidget->setHorizontalHeaderLabels(tableHead);
            }
            flag = 1;
            //更新搜索的结果
            UpdateResultTableWidget(msg);
        }
        else if(kind == "EK"){ //error and disconnected messsage，对登录的信息进行验证
            ContentListWidget->addItem(msg);
            EnterBtn->setText("登陆");
            tcpSocket->disconnectFromHost();
            status = false;
            ShareBtn->setEnabled(false);
            FlushBtn->setEnabled(false);
            DisableBtn->setEnabled(false);
            SearchBtn->setEnabled(false);
            DownloadBtn->setEnabled(false);
            SignBtn->setEnabled(true);
        }
        else if(kind == "OT"){ //normal message，普通的消息，即在记录栏展示的消息
            ContentListWidget->addItem(msg);
        }
        else if(kind == "BP"){ //breakpoint message，断点文件消息
            if(flag == 0){
                ResultTableWidget->clear();
                ResultTableWidget->setRowCount(0);
                QStringList tableHead;
                tableHead << "文件名" << "大小" << "文件路径" << "拥有者" << "状态" << "IP"<< "断点位置" << "选择";
                ResultTableWidget->setHorizontalHeaderLabels(tableHead);
            }
            flag = 1;
            //更新界面
            qDebug() << "BreakPointMsg" << msg << endl;
            UpdateBreakTableWidget(msg);
        }
    }
}

void MainWindow::SignDataReceived(){
    if (tcpSocket->bytesAvailable() > 8){//判断缓冲区中的字节数是否大于8
        char buf[1024];
        tcpSocket->read(buf,8);//从缓冲区中读取8个字节的数据

        //解析消息头
        QString head = buf;
        long msglen = 0;//存储数据的长度
        QString kind;//存储数据的类型
        if(head == "error|||"){
            return;
        }
        else{
            msglen = head.mid(2,6).toLong();
            kind = head.mid(0,2);
            tcpSocket->read(buf,msglen);//读取剩余的数据
            buf[msglen] = 0;//
        }

        QString msg = buf;
        if(kind == "SS"){ //sign success
            ContentListWidget->addItem(msg);//注册成功，将消息打印出来
        }
        else if(kind == "SF"){ //sign fail
            ContentListWidget->addItem(msg);//注册失败，注册按钮设置为可用
            SignBtn->setEnabled(true);
        }
        tcpSocket->disconnectFromHost();//注册流程完成，断开tcp连接
        status = false;//将tcp连接状态设置为未连接
    }
}

void MainWindow::slotDisconnected(){//用户登录的tcp连接断开时，将各个按钮恢复原状
    EnterBtn->setText("登陆");
    ShareBtn->setEnabled(false);
    FlushBtn->setEnabled(false);
    DisableBtn->setEnabled(false);
    SearchBtn->setEnabled(false);
    DownloadBtn->setEnabled(false);
    SignBtn->setEnabled(true);
}

void MainWindow::SignDisconnected(){//注册的tcp的连接断开时，什么都不做
}

//head is 8 bits
void MainWindow::FormatMsg(QString &msg, MsgKind kind){
    qint64 len = msg.length();
    QString s = QString::number(len);
    if(len > 100000){//消息长度过大，信息设置为错误，限制单次传输的数据量
        msg = "error|||";
        return;
    }
    for(int i = s.length(); i < 6; ++i){//将消息头统一为固定长度的字符串
        s = "0" + s;
    }
    switch (kind) {
    case NAMEMSG:
        msg = "NM" + s + msg;
        break;
    case METAMSG:
        msg = "MM" + s + msg;
        break;
    case DISCONNECT:
        msg = "DC" + s + msg;
        break;
    case SHAREMSG:
        msg = "SM" + s + msg;
        break;
    case DELETEMSG:
        msg = "DM" + s + msg;
        break;
    case SEARCHMSG:
        msg = "SR" + s + msg;
        break;
    case SIGNMSG:
        msg = "GM" + s + msg;
        break;
    case OTHERMSG:
        msg = "OT" + s + msg;
        break;
    case BREAKPOINT://向服务器查询断点文件
        msg = "BP" + s + msg;
        break;
    case UPDATELOG://向服务器更新断点日志
        msg = "UL" + s + msg;
        break;
    }
}

void MainWindow::UpdateResultTableWidget(QString &msg){//用于将服务器返回的搜索信息进行渲染，即将文件信息按行展示
    if(msg == ""){//服务器没有搜到东西，直接返回
        return;
    }

    tcp_meta tm(msg);
    int rows = ResultTableWidget->rowCount();

    ResultTableWidget->setRowCount(rows + 1);//新增一行，将获取的数据进行渲染
    QTableWidgetItem *item = new QTableWidgetItem(tm.filename);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 0, item);

    item = new QTableWidgetItem(QString::number(tm.size));
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 1, item);

    item = new QTableWidgetItem(tm.filepath);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 2, item);

    item = new QTableWidgetItem(tm.owner);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 3, item);

    if(tm.online == "on")
        item = new QTableWidgetItem("在线");
    else
        item = new QTableWidgetItem("离线");
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 4, item);

    item = new QTableWidgetItem(tm.ip);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 5, item);

    item = new QTableWidgetItem("-1");//搜索到的文件都当作没有异常中断
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 6, item);

    item = new QTableWidgetItem("check");
    item->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
    item->setCheckState(Qt::Unchecked);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 7, item);

}

void MainWindow::UpdateShareTableWidget(QString &msg){//与上述搜索结果的渲染相同
    if(msg == ""){
        return;
    }

    tcp_meta tm(msg);
    int rows = ShareTableWidget->rowCount();

    ShareTableWidget->setRowCount(rows + 1);
    QTableWidgetItem *item = new QTableWidgetItem(tm.filename);
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 0, item);
    item = new QTableWidgetItem(QString::number(tm.size));
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 1, item);
    item = new QTableWidgetItem(tm.filepath);
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 2, item);
    item = new QTableWidgetItem(tm.ip);
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 3, item);
    item = new QTableWidgetItem(QString::number(tm.port));
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 4, item);
    item = new QTableWidgetItem("check");
    item->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
    item->setCheckState(Qt::Unchecked);
    item->setTextAlignment(Qt::AlignCenter);
    ShareTableWidget->setItem(rows, 5, item);

}

void MainWindow::UpdateBreakTableWidget(QString &msg){//与上述搜索结果的渲染相同
    if(msg == ""){
        return;
    }

    tcp_meta tm(msg);
    int rows = ResultTableWidget->rowCount();

    ResultTableWidget->setRowCount(rows + 1);
    QTableWidgetItem *item = new QTableWidgetItem(tm.filename);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 0, item);

    item = new QTableWidgetItem(QString::number(tm.size));
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 1, item);

    item = new QTableWidgetItem(tm.filepath);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 2, item);

    item = new QTableWidgetItem(tm.owner);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 3, item);

    if(tm.online == "on")
        item = new QTableWidgetItem("在线");
    else
        item = new QTableWidgetItem("离线");
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 4, item);

    item = new QTableWidgetItem(tm.ip);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 5, item);

    item = new QTableWidgetItem(tm.breakpoint);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 6, item);

    item = new QTableWidgetItem("check");
    item->setFlags(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled|Qt::ItemIsSelectable);
    item->setCheckState(Qt::Unchecked);
    item->setTextAlignment(Qt::AlignCenter);
    ResultTableWidget->setItem(rows, 7, item);


}

void MainWindow::previewAll(){
    qDebug()<<"previewAll进来了";
    QString dirname = DirLineEdit->text();
    if(dirname == ""){
        return;
    }
    int rows = ResultTableWidget->rowCount();
    for(int i = 0; i < rows; ++i){
        qDebug()<<"previewAll循环进来了";
        if(ResultTableWidget->item(i,7)->checkState() == Qt::Checked
            && ResultTableWidget->item(i,4)->text() == "在线"){//该行选中且在线
            QString fileName = ResultTableWidget->item(i,0)->text();
            QString filePath = dirname+fileName;//文件路径
            qDebug()<<"filePath:"<<filePath;
            if(ProgressBar->value()==100){
                QDesktopServices::openUrl(QUrl::fromLocalFile(filePath));
            }else{
                QFileInfo fileInfo(filePath);
                QMimeType mimeType = QMimeDatabase().mimeTypeForFile(filePath);

                if (mimeType.name().startsWith("image/")) {
                    // 文件是JPEG图像
                    previewImage(filePath);
                    qDebug() << fileInfo.fileName() << "是图像。";
                } else if (mimeType.name().startsWith("text/")) {
                    // 文件是纯文本文件
                    previewText(filePath);
                    qDebug() << fileInfo.fileName() << "是纯文本文件。";
                } else if(mimeType.name().startsWith("video/")){
                    // 文件是视频
                    previewVideo(filePath);
                    qDebug() << fileInfo.fileName() << "是视频类型。";
                }
            }

        }
    }
}

void MainWindow::previewImage(QString filePath){
    QWidget* widget = new QWidget();
    QLabel * previewLabel = new QLabel(widget);
    QPixmap placeholderPixmap(":/placeholder.png"); // 占位图
    previewLabel->setPixmap(placeholderPixmap);

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file" << filePath;
        return;
    }

    QByteArray bytes = file.readAll(); // 读取文件
    QBuffer buffer(&bytes);
    buffer.open(QIODevice::ReadOnly);

    QImageReader reader(&buffer);
    QImage image = reader.read(); // 读取图像

    if (image.isNull()) {
        qDebug() << "Failed to load image" << filePath;
        return;
    }

    previewLabel->setPixmap(QPixmap::fromImage(image)); // 显示图像
    previewLabel->setFixedSize(image.width(), image.height());
    widget->resize(previewLabel->size());

    widget->show();
}


void MainWindow::previewText(QString filePath){
    QWidget* widget = new QWidget();
    QTextEdit* previewtext = new QTextEdit(widget);
    previewtext->setReadOnly(true);
    previewtext->setPlainText("");

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug() << "Failed to open file" << filePath;
        return;
    }
    else {
        QTextStream textStream(&file);
        textStream.setCodec("UTF-8"); //设置编码格式为UTF-8
        previewtext->setPlainText(textStream.readAll());
        file.close();
    }

    previewtext->resize(600,400);
    widget->resize(600,400);

    // 显示 QWidget
    widget->show();
}

void MainWindow::previewVideo(QString filePath){
    QWidget* widget = new QWidget();
    // 创建 QVideoWidget 并将其嵌套进 QWidget 中
    QVideoWidget* videoWidget = new QVideoWidget(widget);
    videoWidget->setFixedSize(600, 400);

    // 创建 mediaPlayer 对象
    QMediaPlayer* mediaPlayer = new QMediaPlayer(widget);

    // 将 mediaPlayer 的媒体对象设置为 videoWidget
    mediaPlayer->setVideoOutput(videoWidget);

    // 创建 mediaPlayer 控制界面
    QHBoxLayout* controlLayout = new QHBoxLayout(widget);
    QPushButton* playButton = new QPushButton("Play", widget);
    QPushButton* stopButton = new QPushButton("Stop", widget);
    QSlider* volumeSlider = new QSlider(Qt::Horizontal, widget);
    controlLayout->addWidget(playButton);
    controlLayout->addWidget(stopButton);
    controlLayout->addWidget(volumeSlider);
    controlLayout->addStretch();
    widget->setLayout(controlLayout);

    // 将 mediaPlayer 控制界面连接到 mediaPlayer 的槽
    connect(playButton, &QPushButton::clicked, mediaPlayer, &QMediaPlayer::play);
    connect(stopButton, &QPushButton::clicked, mediaPlayer, &QMediaPlayer::stop);
    connect(volumeSlider, &QSlider::valueChanged, mediaPlayer, &QMediaPlayer::setVolume);

    // 打开视频文件
    mediaPlayer->setMedia(QUrl::fromLocalFile(filePath));

    // 播放
    mediaPlayer->play();

    // 显示 QWidget
    widget->show();
}

MainWindow::~MainWindow()
{
    delete PortLabel;
    delete PortLineEdit;
    delete EnterBtn;
    delete SignBtn;
    delete UserNameLabel;
    delete UserNameLineEdit;
    delete UserPasswdLabel;
    delete UserPasswdLineEdit;
    delete ServerIPLabel;
    delete ServerIPLineEdit;
    delete ContentListWidget;
    delete ShareTableWidget;
    delete DisableBtn;
    delete FlushBtn;
    delete ResultTableWidget;
    delete SearchLineEdit;
    delete SearchBtn;
    delete DownloadBtn;
    delete timer;
    delete ProgressBar;
    delete SelectDirBtn;
    delete DirLineEdit;
    delete layout1;
    delete layout2;
    delete layout3;
    delete mainLayout;
    delete myWidget;
    delete ServerIP;
    if(tcpSocket != nullptr){
        delete tcpSocket;
    }
}


void MainWindow::store(QString serverIp, QString username, QString password){
    this->UserName = username;
}
